/**
 * Licensed under the MIT License
 *
 * Copyright (c) 2010 Alexandre Croiseaux
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */
package marcel.display.gui.components
{
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;
	import flash.geom.Rectangle;
	import flash.utils.getDefinitionByName;
	import marcel.debug.debugw;
	import marcel.display.gui.form.IFormComponent;
	import marcel.display.gui.texts.CoreField;
	import marcel.display.View;
	import swc.form.CheckBoxAsset;
	
	/**
	* Dispatched when the value has changed
	* @eventType flash.events.Event.CHANGE
	*/
	[Event(name = "change", type = "flash.events.Event")]

	/**
	 * A Checkbox component class to use in forms.
	 * The graphics are editable inside the form.fla file
	 * @author Alexandre Croiseaux
	 */
	public class CheckBox extends View implements IFormComponent
	{
		/**
		 * @private
		 */
		protected var _gfx : MovieClip;
		/**
		 * @private
		 */
		protected var _mcBg : MovieClip;
		/**
		 * @private
		 */
		protected var _mcTicker : MovieClip;
		/**
		 * @private
		 */
		protected var _bIsSelected : Boolean;
		/**
		 * @private
		 */
		protected var _textField : CoreField;
		
		//--------------------------------------------------------------------------
		//
		//  Constructor
		//
		//--------------------------------------------------------------------------
		/**
		 * Constructs a new Checkbox instance using the gfx of the form.swc file
		 */
		public function CheckBox(text:String = null, classStyle:String = null, cssId:String = null, rendererClassOrClassName:* = "swc.form.CheckBoxAsset")
		{
			var clazz:Class;
			try
			{
				if (rendererClassOrClassName is Class) clazz = rendererClassOrClassName;
				else clazz = getDefinitionByName(rendererClassOrClassName) as Class;
			}
			catch (e:Error)
			{
				debugw("Renderer class not found (" + rendererClassOrClassName + ") => using swc.form.CheckBoxAsset");
				clazz = CheckBoxAsset;
			}
			
			_gfx = new clazz();
			_gfx.mouseChildren = false;
			addChild(_gfx);
			_mcBg = _gfx.mcBg;
			_mcTicker = _gfx.mcTicker;
			_bIsSelected = _mcTicker.visible;
			_initInteractivity();
			_textField = new CoreField();
			_textField.x = _gfx.width + 5;
			_textField.mouseEnabled = false;
			
			if (classStyle) setStyle(classStyle, cssId);
			if (text) this.text = text;
		}
		
		//--------------------------------------------------------------------------
		//
		//  Public methods
		//
		//--------------------------------------------------------------------------
		/**
		 * Defines a clickable rectangle allowing to change the current checkbox value
		 * @param	oRect
		 */
		public function setActiveZone(oRect : Rectangle) : void {
			var doRec : Shape = new Shape();
			doRec.graphics.beginFill(0, 0);
			doRec.graphics.drawRect(oRect.x, oRect.y, oRect.width, oRect.height);
			_gfx.addChild(doRec);
		}
		
		/**
		 * Defines a text to display on the right of the checkbox
		 */
		public function set text(str:String):void
		{
			if (!contains(_textField)) addChild(_textField);
			_textField.htmlText = str;
			var r:Rectangle = _textField.getRect(this);
			r.x -= _textField.x;
			r.width += _textField.x;
			setActiveZone(r);
		}
		
		/**
		 * Sets the css style of the inner textfield.
		 * @param	classStyle	the style of text to apply
		 * @param	cssId	the css id to get the style class from
		 */
		public function setStyle(classStyle:String, cssId:String = null):void
		{
			_textField.setCSSStyle(classStyle, cssId);
		}
		
		/**
		 * Toggle the state of the checkbox
		 */
		public function toggle() : void {
			_bIsSelected = !_bIsSelected;
			_mcTicker.visible = _bIsSelected;
			dispatchEvent(new Event(Event.CHANGE));
		}
		
		/**
		 * Returns the state of the checkbox as a boolean, true if selected, false otherwise. Casted as * to implement IFormComponent interface
		 * This method is an alias of the 'selected' property
		 * @return	true if the checkbox is selected, false otherwise
		 */
		public function getValue() : * {
			return selected;
		}
		
		/**
		 * Sets the selected state of the current CheckBox.
		 * @param	oValue	a text string
		 */
		public function setValue(oValue:*) : void
		{
			selected = Boolean(oValue);
		}
		
		/**
		 * Indicates and set the value of the current checkbox (true if the checkbox is selected, false otherwise)
		 */
		public function get selected():Boolean { return _bIsSelected; }
		public function set selected(value:Boolean):void
		{
			_bIsSelected = value;
			_mcTicker.visible = value;
		}
		
		/**
		 * Displays the current component as having an error or not. This method is automatically called by the Form class if form.useHighlight is set to true.
		 * @param	hasError	Indicates if there is an error or not.
		 */
		public function displayError(hasError:Boolean):void
		{
			_gfx.filters = hasError ? [new GlowFilter(0xFF0000, 1, 2, 2, 2, 3, true, false)] : null;
		}
		
		//--------------------------------------------------------------------------
		//
		//  Private methods
		//
		//--------------------------------------------------------------------------
		/**
		 * @private
		 */
		protected function _initInteractivity() : void {
			_gfx.buttonMode = true;
			_gfx.addEventListener(MouseEvent.CLICK, _onPress);
		}
			
		//--------------------------------------------------------------------------
		//
		//  Events
		//
		//--------------------------------------------------------------------------
		protected function _onPress(event : MouseEvent) : void {
			toggle();
		}
	}
}
